/*
 Copyright (c) 2024 Broin All rights reserved.
 Use of this source code is governed by a BSD-style
 license that can be found in the LICENSE file.
 */

#ifndef POLICY_H
#define POLICY_H

#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <cjson/cJSON.h>
#include <dirent.h>
#include <sys/types.h>
#include <pwd.h>

#include "./struct.h"
#include "./utils.h"
#include "./bpf_map.h"

/* 定义路径长度与路径集合大小 */
#ifndef POLICY_PATH
#define POLICY_PATH
#define MAX_PATH_LEN 512
#define MAX_PATH_LIST_SIZE 64
#endif // !! POLICY_PATH


/* ---------------------策略相关功能接口 --------------------------*/

/* 策略处理接口 */
/**
 * @description: 将操作转换为判定
 * @param {char} *access
 * @return {*}
 */
file_permission_t file_access_to_decision(char *access)
{
    int i;
    int len = strlen(access);
    file_permission_t perm = 0x0;

    for (i = 0; i < len; ++i)
    {
        char c = access[i];
        if ('r' == c)
        {
            perm |= FILE_MAY_READ;
        }
        else if ('w' == c)
        {
            perm |= FILE_MAY_WRITE;
        }
        else if ('x' == c)
        {
            perm |= FILE_MAY_EXEC;
        }
        else if ('l' == c)
        {
            perm |= FILE_MAY_LINK;
        }
        else if ('d' == c)
        {
            perm |= FILE_MAY_DELETE;
        }
        else if ('a' == c)
        {
            perm |= FILE_MAY_APPEND;
        }
    }

    return perm;
}

/**
 * @description: 将操作转换为判定
 * @param {char} *access
 * @return {*}
 */
net_opt_t net_access_to_permission(char *access)
{
    int len = strlen(access);
    net_opt_t perm = 0x00000000;

    int i = 0;
    for (i = 0; i < len; i++)
    {
        switch (access[i])
        {
        case 'L':
            perm |= NETWORK_MAY_SOCKET_LISTEN;
            break;
        case 'C':
            perm |= NETWORK_MAY_SOCKET_CONNECT;
            break;
        case 'R':
            perm |= NETWORK_MAY_SOCKET_CREATE;
            break;
        case 'A':
            perm |= NETWORK_MAY_SOCKET_ACCEPT;
            break;
        default:
            break;
        }
    }

    return perm;
}

/**
 * @desciption: 将JSON中对应不同类型的主体字符串转为枚举类型
 * @param 主体类型字符串
 * @return 主体类型枚举
 */

subtype_t get_subtype(const char *type)
{
    if (strcmp(type, "proc") == 0)
        return PROC;
    if (strcmp(type, "user") == 0)
        return USER;

    return PROC;
}

/**
 * @description: 将json数据中的"roles"成员提取为字符串数组
 * @param {cJSON} *policy_data
 * @param {char} *
 * @return {*}
 */
int policy_json_extract_role(cJSON *policy_data, char **roles)
{
    int ret = 0;
    int i;
    int ret_role_count = 0;
    cJSON *json_roles = cJSON_GetObjectItemCaseSensitive(policy_data, "roles");
    if (cJSON_IsArray(json_roles))
    {
        int count = cJSON_GetArraySize(json_roles);
        for (i = 0; i < count; ++i)
        {
            cJSON *role = cJSON_GetArrayItem(json_roles, i);
            if (cJSON_IsString(role) && (NULL != role->valuestring))
            {
                strcpy(roles[i], role->valuestring);
                ret_role_count++;
            }
        }
    }
    ret += ret_role_count;
    return ret;
}

/**
 * @description: 将roles添加进role_map
 * @param {ROLE_MAP} *role_map
 * @param {char} *
 * @param {int} role_length
 * @return {*}
 */
int policy_role_append(ROLE_MAP *role_map, char **roles, int role_length)
{
    int ret = 0;
    int i;
    for (i = 0; i < role_length; ++i)
    {
        ret = hash_map_insert(role_map, roles[i]);
        u32 value = -1;
        ret = hash_map_search(role_map, roles[i], &value);
        if (!ret)
        {
            ebpflsm_error("插入role_map不成功, roles[i]: %s, value: %lu", roles[i], value);
        }
    }
    return ret;
}

/**
 * @description: 解析json数据，将之主体和角色的映射关系放入sub2role map中
 * @param {cJSON} *policy_data
 * @param {POLICY_SKEL} *skel
 * @param {ROLE_MAP} *role_map
 * @return {*}
 */
int policy_addmap_sub2role(cJSON *policy_data, POLICY_SKEL *skel, ROLE_MAP *role_map)
{
    int ret = 0;
    int i;
    int map_fd = bpf_map__fd(skel->maps.sub_to_role);
    int ret_add_count = 0;

    cJSON *sub2roles = cJSON_GetObjectItemCaseSensitive(policy_data, "subject");
    if (cJSON_IsArray(sub2roles))
    {
        int count = cJSON_GetArraySize(sub2roles);
        for (i = 0; i < count; ++i)
        {
            cJSON *item = cJSON_GetArrayItem(sub2roles, i);

            cJSON *json_subtype = cJSON_GetObjectItemCaseSensitive(item, "type");
            cJSON *json_sub = cJSON_GetObjectItemCaseSensitive(item, "subject_name");
            cJSON *json_role = cJSON_GetObjectItemCaseSensitive(item, "role");

            subtype_t subtype = get_subtype(json_subtype->valuestring);

            // 制作subject和role的相关信息
            subject_t sub = {};
            role_t role = {};
            u32 role_id = 0;

            // 根据主体信息的类型去填充uion的相应字段,制作主体
            if (subtype == PROC)
            {
                sub.type = subtype;
                strcpy(sub.comm, json_sub->valuestring);
                ret = strlen(sub.comm);
                if (0 >= ret)
                {
                    ebpflsm_error("没有这个主体, sub.comm : %s", sub.comm);
                    continue;
                }
            }
            else if (subtype == USER)
            {
                sub.type = subtype;
                sub.uid = get_uid(json_sub->valuestring);
                if (sub.uid == __INT_MAX__)
                {
                    ebpflsm_error("系统中没有这个用户 %s \n", json_sub->valuestring);
                    continue;
                }
            }

            strcpy(role.role_name, json_role->valuestring);
            ret = hash_map_search(role_map, role.role_name, &role_id);
            if (!ret)
            {
                ebpflsm_error("没有这个角色, role_name : %s", role.role_name);
                continue;
            }
            role.id = role_id;

            // 更新map
            update_sub2role(map_fd, &sub, &role);
            ret_add_count++;
        }
    }
    ret += ret_add_count;
    return ret;
}

int policy_addmap_fs_whole(cJSON *fs_whole_policy, POLICY_SKEL *skel)
{
    int ret = 0;

    return ret;
}

/**
 * @description:
 * @param {cJSON} *file_whole_policy
 * @param {POLICY_SKEL} *skel
 * @return {*}
 */
int policy_addmap_file_whole(cJSON *file_whole_policy, POLICY_SKEL *skel)
{
    int ret = 0;
    int count;
    int policy_append_size = 0;
    int i;
    int map_fd;

    cJSON *allow = cJSON_GetObjectItemCaseSensitive(file_whole_policy, "allow");
    if (cJSON_IsArray(allow))
    {
        count = cJSON_GetArraySize(allow);
        for (i = 0; i < count; ++i)
        {
            cJSON *policy = cJSON_GetArrayItem(allow, i);
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");
            cJSON *container = cJSON_GetObjectItemCaseSensitive(policy, "container");
            file_permission_t allow_policy = file_access_to_decision(access->valuestring);
            u64 file_ino = 0;
            char container_name[256];
            strncpy(container_name, container->valuestring, sizeof(container_name) - 1);
            container_name[sizeof(container_name) - 1] = '\0';
            file_policy_val_t policy_val = {0x0, 0x0};
            if (!strcmp(container_name, ""))
            {
                if (cJSON_IsString(object) && (NULL != object->valuestring))
                {
                    file_ino = path_to_ino(object->valuestring);
                }
                // 更新策略信息
                map_fd = bpf_map__fd(skel->maps.whole_file_policy);
                ret = bpf_map_lookup_elem(map_fd, &file_ino, &policy_val);
                policy_val.allow |= allow_policy;
                ret = update_wholefilepolicy(map_fd, &file_ino, &policy_val);
                policy_append_size++;
            }
            else
            {
                policy_container_val_t policy_container_val;
                policy_container_val.allow = 0x0;
                policy_container_val.deny = 0x0;
                map_fd = bpf_map__fd(skel->maps.container_policy);
                ret = bpf_map_lookup_elem(map_fd, &container_name, &policy_container_val);
                strncpy(policy_container_val.path, object->valuestring, sizeof(policy_container_val.path) - 1);
                policy_container_val.path[sizeof(policy_container_val.path) - 1] = '\0';
                policy_container_val.allow |= allow_policy;
                ret = bpf_map_update_elem(map_fd, &container_name, &policy_container_val, BPF_ANY);
                policy_append_size++;
            }
        }
    }

    cJSON *deny = cJSON_GetObjectItemCaseSensitive(file_whole_policy, "deny");
    if (cJSON_IsArray(deny))
    {
        count = cJSON_GetArraySize(deny);
        for (i = 0; i < count; ++i)
        {
            cJSON *policy = cJSON_GetArrayItem(deny, i);
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");
            cJSON *container = cJSON_GetObjectItemCaseSensitive(policy, "container");
            file_permission_t deny_policy = file_access_to_decision(access->valuestring);
            u64 file_ino = 0;
            char container_name[256];
            strncpy(container_name, container->valuestring, sizeof(container_name) - 1);
            container_name[sizeof(container_name) - 1] = '\0';
            file_policy_val_t policy_val = {0x0, 0x0};
            if (!strcmp(container_name, ""))
            {
                if (cJSON_IsString(object) && (NULL != object->valuestring))
                {
                    file_ino = path_to_ino(object->valuestring);
                }

                // 更新策略信息
                map_fd = bpf_map__fd(skel->maps.whole_file_policy);
                ret = bpf_map_lookup_elem(map_fd, &file_ino, &policy_val);
                policy_val.deny |= deny_policy;
                ret = update_wholefilepolicy(map_fd, &file_ino, &policy_val);
                policy_append_size++;
            }
            else
            {
                policy_container_val_t policy_container_val;
                policy_container_val.allow = 0x0;
                policy_container_val.deny = 0x0;
                map_fd = bpf_map__fd(skel->maps.container_policy);
                ret = bpf_map_lookup_elem(map_fd, &container_name, &policy_container_val);
                strncpy(policy_container_val.path, object->valuestring, sizeof(policy_container_val.path) - 1);
                policy_container_val.path[sizeof(policy_container_val.path) - 1] = '\0';
                policy_container_val.deny |= deny_policy;
                ret = bpf_map_update_elem(map_fd, &container_name, &policy_container_val, BPF_ANY);
                policy_append_size++;
            }
        }
    }

    ret += policy_append_size;
    return ret;
}

int policy_addmap_net_whole(cJSON *net_whole_policy, POLICY_SKEL *skel)
{
    int ret = 0;
    int count;
    int policy_append_size = 0;
    int i;
    int map_fd;

    cJSON *allow = cJSON_GetObjectItemCaseSensitive(net_whole_policy, "allow");
    if (cJSON_IsArray(allow))
    {
        count = cJSON_GetArraySize(allow);
        map_fd = bpf_map__fd(skel->maps.whole_net_policy);

        for (i = 0; i < count; i++)
        {
            cJSON *policy = cJSON_GetArrayItem(allow, i);
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");

            net_opt_t allow_policy = net_access_to_permission(access->valuestring);
            u32 ip = convert_ipstr(object->valuestring);

            net_policy_val_t policy_val = {0x00000000, 0x00000000};

            bpf_map_lookup_elem(map_fd, &ip, &policy_val);
            policy_val.allow |= allow_policy;
            update_wholenetpolicy(map_fd, ip, &policy_val);

            policy_append_size++;
        }
    }

    cJSON *deny = cJSON_GetObjectItemCaseSensitive(net_whole_policy, "deny");
    if (cJSON_IsArray(deny))
    {
        count = cJSON_GetArraySize(deny);
        map_fd = bpf_map__fd(skel->maps.whole_net_policy);

        for (i = 0; i < count; i++)
        {
            cJSON *policy = cJSON_GetArrayItem(deny, i);
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");

            net_opt_t deny_policy = net_access_to_permission(access->valuestring);
            u32 ip = convert_ipstr(object->valuestring);

            net_policy_val_t policy_val = {0x00000000, 0x00000000};

            bpf_map_lookup_elem(map_fd, &ip, &policy_val);
            policy_val.deny |= deny_policy;
            update_wholenetpolicy(map_fd, ip, &policy_val);

            policy_append_size++;
        }
    }
    ret += policy_append_size;

    return ret;
}

int policy_addmap_fs(cJSON *fs_policy, POLICY_SKEL *skel, ROLE_MAP *role_map)
{
    int ret = 0;

    return ret;
}

/**
 * @description:
 * @param {cJSON} *file_policy
 * @param {POLICY_SKEL} *skel
 * @param {ROLE_MAP} *role_map
 * @return {*}
 */
int policy_addmap_file(cJSON *file_policy, POLICY_SKEL *skel, ROLE_MAP *role_map)
{
    int ret = 0;
    int count;
    int policy_append_size = 0;
    int i;
    int map_fd;

    cJSON *allow = cJSON_GetObjectItemCaseSensitive(file_policy, "allow");
    if (cJSON_IsArray(allow))
    {
        count = cJSON_GetArraySize(allow);
        for (i = 0; i < count; ++i)
        {
            cJSON *policy = cJSON_GetArrayItem(allow, i);
            cJSON *role = cJSON_GetObjectItemCaseSensitive(policy, "role");
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");
            file_permission_t allow_policy = file_access_to_decision(access->valuestring);
            u64 file_ino = 0;
            file_policy_key_t policy_key = {0x0, 0x0};
            file_policy_val_t policy_val = {0x0, 0x0};

            // 填充主题信息
            if (cJSON_IsString(object) && (NULL != object->valuestring))
            {
                file_ino = path_to_ino(object->valuestring);
            }
            u32 role_id = 0x0;
            ret = hash_map_search(role_map, role->valuestring, &role_id);
            policy_key.role_id = role_id;
            policy_key.inode_id = file_ino;

            // 更新策略信息
            map_fd = bpf_map__fd(skel->maps.file_policy);
            ret = bpf_map_lookup_elem(map_fd, &policy_key, &policy_val);
            policy_val.allow |= allow_policy;
            ret = update_filepolicy(map_fd, &policy_key, &policy_val);
            policy_append_size++;
        }
    }

    cJSON *deny = cJSON_GetObjectItemCaseSensitive(file_policy, "deny");
    if (cJSON_IsArray(deny))
    {
        count = cJSON_GetArraySize(deny);
        for (i = 0; i < count; ++i)
        {
            cJSON *policy = cJSON_GetArrayItem(deny, i);
            cJSON *role = cJSON_GetObjectItemCaseSensitive(policy, "role");
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");
            file_permission_t deny_policy = file_access_to_decision(access->valuestring);
            u64 file_ino = 0;
            file_policy_key_t policy_key = {0x0, 0x0};
            file_policy_val_t policy_val = {0x0, 0x0};

            // 填充主体信息
            if (cJSON_IsString(object) && (NULL != object->valuestring))
            {
                file_ino = path_to_ino(object->valuestring);
            }
            u32 role_id = 0x0;
            ret = hash_map_search(role_map, role->valuestring, &role_id);
            policy_key.role_id = role_id;
            policy_key.inode_id = file_ino;

            // 更新策略信息
            map_fd = bpf_map__fd(skel->maps.file_policy);
            ret = bpf_map_lookup_elem(map_fd, &policy_key, &policy_val);
            policy_val.deny |= deny_policy;
            ret = update_filepolicy(map_fd, &policy_key, &policy_val);
            policy_append_size++;
        }
    }

    ret += policy_append_size;
    return ret;
}

/**
 * @description:
 * @param {cJSON} *net_policy
 * @param {POLICY_SKEL} *skel
 * @param {ROLE_MAP} *role_map
 * @return {*}
 */
int policy_addmap_net(cJSON *net_policy, POLICY_SKEL *skel, ROLE_MAP *role_map)
{
    int ret = 0;
    int count = 0;
    int policy_append_size = 0;
    int i;
    int map_fd;

    cJSON *allow = cJSON_GetObjectItemCaseSensitive(net_policy, "allow");
    if (cJSON_IsArray(allow))
    {

        count = cJSON_GetArraySize(allow);
        map_fd = bpf_map__fd(skel->maps.net_policy);

        for (i = 0; i < count; i++)
        {
            // 获取相应的json数据
            cJSON *policy = cJSON_GetArrayItem(allow, i);
            cJSON *role = cJSON_GetObjectItemCaseSensitive(policy, "role");
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");
            net_opt_t allow_policy = net_access_to_permission(access->valuestring);
            // 制作策略键,与策略值
            net_policy_key_t policy_key = {0x00000000, 0x00000000};
            net_policy_val_t policy_val = {0x00000000, 0x00000000};

            u32 role_id = 0;
            u32 ip = 0;

            hash_map_search(role_map, role->valuestring, &role_id);
            ip = convert_ipstr(object->valuestring);

            policy_key.role_id = role_id;
            policy_key.ip = ip;

            bpf_map_lookup_elem(map_fd, &policy_key, &policy_val);
            policy_val.allow |= allow_policy;
            ret = update_netpolicy(map_fd, &policy_key, &policy_val);

            policy_append_size++;
        }
    }

    cJSON *deny = cJSON_GetObjectItemCaseSensitive(net_policy, "deny");
    if (cJSON_IsArray(deny))
    {
        count = cJSON_GetArraySize(deny);
        map_fd = bpf_map__fd(skel->maps.net_policy);

        for (i = 0; i < count; i++)
        {
            cJSON *policy = cJSON_GetArrayItem(deny, i);
            cJSON *role = cJSON_GetObjectItemCaseSensitive(policy, "role");
            cJSON *object = cJSON_GetObjectItemCaseSensitive(policy, "object");
            cJSON *access = cJSON_GetObjectItemCaseSensitive(policy, "access");
            net_opt_t deny_policy = net_access_to_permission(access->valuestring);

            // 制作策略键,与策略值
            net_policy_key_t policy_key = {0x00000000, 0x00000000};
            net_policy_val_t policy_val = {0x00000000, 0x00000000};

            u32 role_id = 0;
            u32 ip = 0;

            hash_map_search(role_map, role->valuestring, &role_id);
            ip = convert_ipstr(object->valuestring);

            policy_key.role_id = role_id;
            policy_key.ip = ip;

            bpf_map_lookup_elem(map_fd, &policy_key, &policy_val);
            policy_val.deny |= deny_policy;

            ret = update_netpolicy(map_fd, &policy_key, &policy_val);

            policy_append_size++;
        }
    }
    ret += policy_append_size;

    return ret;
}

/**
 * @description: 通过json数据，将所有策略存入ebpflsm的map
 * @param {cJSON} *policy_data: 访控策略的json数据
 * @param {char} *file_path: 访控策略文件路径，用于审计定位
 * @param {POLICY_SKEL} *skel: ebpf骨架skel
 * @param {ROLE_MAP} *role_map: 角色哈希表
 * @return {int} : 0表示成功，-1表示失败
 */
int policy_addmap_all(cJSON *file_policy_data, char *file_path, POLICY_SKEL *skel, ROLE_MAP *role_map)
{
    int ret = 0;
    int count = 0;

    /* 全局策略处理 */
    cJSON *policy_data_list = cJSON_GetObjectItemCaseSensitive(file_policy_data, "policy");
    if (cJSON_IsArray(policy_data_list))
    {
        cJSON *policy_data;
        cJSON_ArrayForEach(policy_data, policy_data_list)
        {
            // fs全局策略
            cJSON *fs_whole_policy = cJSON_GetObjectItemCaseSensitive(policy_data, "fs_whole_policy");
            ret = policy_addmap_fs_whole(fs_whole_policy, skel);
            count += ret;

            // file 全局策略
            cJSON *file_whole_policy = cJSON_GetObjectItemCaseSensitive(policy_data, "file_whole_policy");
            ret = policy_addmap_file_whole(file_whole_policy, skel);
            count += ret;

            // net 全局策略
            cJSON *net_whole_policy = cJSON_GetObjectItemCaseSensitive(policy_data, "net_whole_policy");
            ret = policy_addmap_net_whole(net_whole_policy, skel);
            count += ret;

            /* 引入角色的策略处理 */
            // fs策略
            cJSON *fs_policy = cJSON_GetObjectItemCaseSensitive(policy_data, "fs_policy");
            ret = policy_addmap_fs(fs_policy, skel, role_map);
            count += ret;

            // file 策略
            cJSON *file_policy = cJSON_GetObjectItemCaseSensitive(policy_data, "file_policy");
            ret = policy_addmap_file(file_policy, skel, role_map);

            cJSON *net_policy = cJSON_GetObjectItemCaseSensitive(policy_data, "net_policy");
            ret = policy_addmap_net(net_policy, skel, role_map);
            count += ret;
        }
    }

    if (count)
    {
        ebpflsm_normal("Add %d policies to map from policy file: %s", count, file_path);
    }
    return ret;
}

/**
 * @description: [当前建议调用]通过策略文件路径，传入已知的角色哈希表和ebpf的骨架skel，
 * 将所有策略文件中的策略更新到对应的策略map中
 * @param {char} *policy_path
 * @param {ROLE_MAP} *role_map
 * @param {POLICY_SKEL} *skel
 * @return {*}
 */
int policy_file_to_ebpfmap(char *policy_path, ROLE_MAP *role_map, POLICY_SKEL *skel)
{
    // 1. 读取策略文件
    // 2. 提取所有的role并放入hash
    // 3. 提取sub-role并存入map
    // 4. 解析policy_type和策略(role、other:access)
    // 5. 存储相应策略到对应策略map中
    int ret = 0;
    char **roles = array_string_alloc(MAX_ROLE_SIZE, MAX_ROLE_NAME_LEN);

    cJSON *policy_json_data = parse_jsonfile(policy_path);
    if (NULL == policy_json_data)
    {
        const char *error_ptr = cJSON_GetErrorPtr();
        if (NULL != error_ptr)
        {
            fprintf(stderr, "Error before: %s\n", error_ptr);
            ebpflsm_error("Get Policy json file error, ptr addr is : %s", error_ptr);
        }
        ret = -1;
        return ret;
    }

    ret = policy_json_extract_role(policy_json_data, roles);
    ret = policy_role_append(role_map, roles, ret);

    ret = policy_addmap_sub2role(policy_json_data, skel, role_map);

    ret = policy_addmap_all(policy_json_data, policy_path, skel, role_map);

    // free temp data.
    cJSON_Delete(policy_json_data);
    array_string_free(roles, MAX_ROLE_SIZE);

    return ret;
}

/**
 * @description: 将所有目标目录或文件中的策略文件存入对应的策略map中
 * TODO：这个部分需要继续完成预处理的设置部分：客制化的目录和文件路径读取后放入存入dir_or_files
 * @param {char} *
 * @param {POLICY_SKEL} *skel
 * @return {*}
 */
int policy_add_all_file_to_map(const char *dir, ROLE_MAP *role_map, POLICY_SKEL *skel)
{
    int ret = 0;
    struct dirent *entry;
    DIR *dp = opendir(dir);

    if (NULL == dp)
    {
        ebpflsm_error("打开文件夹错误:%s", dir);
        return -1;
    }

    while ((entry = readdir(dp)))
    {
        char fullpath[1024];
        snprintf(fullpath, sizeof(fullpath), "%s/%s", dir, entry->d_name);

        // 跳过".", ".."
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
        {
            continue;
        }

        struct stat sb;

        if (stat(fullpath, &sb) == -1)
        {
            ebpflsm_error("无法获取路径信息:%s", fullpath);
            continue;
        }

        if (S_ISDIR(sb.st_mode))
        {
            // 目录就递归
            policy_add_all_file_to_map(fullpath, role_map, skel);
        }
        else if (S_ISREG(sb.st_mode))
        {
            // 判断文件是否是json
            if (strstr(entry->d_name, ".json"))
            {
                ebpflsm_info("获取json文件: %s", fullpath);
                policy_file_to_ebpfmap(fullpath, role_map, skel);
            }
        }
    }

    closedir(dp);
    return ret;
}

#endif // !POLICY_H
